package cn.yangliu.nacos.comm.handler.flux;

import java.util.List;

import cn.yangliu.nacos.comm.JsonResult;
import com.google.common.base.Preconditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.core.MethodParameter;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.reactive.HandlerResult;
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
import org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 统一响应结构体
 *
 * @author 问道于盲
 * @date 2019 -12-08
 */
@ConditionalOnMissingClass("org.springframework.cloud.gateway.filter.GlobalFilter")
@RestControllerAdvice
@ConditionalOnClass(ResponseBodyResultHandler.class)
public class GlobalResponseBodyResultHandler extends ResponseBodyResultHandler {

    /**
     * Instantiates a new Global response body result handler.
     *
     * @param writers  the writers
     * @param resolver the resolver
     */
    @Autowired
    public GlobalResponseBodyResultHandler(List<HttpMessageWriter<?>> writers, RequestedContentTypeResolver resolver) {
        super(writers, resolver);
    }


    /**
     * Supports boolean.
     *
     * @param handlerResult the handler result
     * @return the boolean
     */
    @Override
    public boolean supports(HandlerResult handlerResult) {
        return super.supports(handlerResult);
    }

    /**
     * Handle result mono.
     *
     * @param serverWebExchange the server web exchange
     * @param handlerResult     the handler result
     * @return the mono
     */
    @SuppressWarnings("unchecked")
    @Override
    public Mono<Void> handleResult(ServerWebExchange serverWebExchange, HandlerResult handlerResult) {
        Object returnValue = handlerResult.getReturnValue();
        Preconditions.checkNotNull(returnValue, "response is null!");
        MethodParameter bodyTypeParameter = handlerResult.getReturnTypeSource();
        Mono<JsonResult<Object>> body;
        if (returnValue instanceof Mono) {
            body = ((Mono<Object>) returnValue).map(JsonResult::getInstance)
                    .defaultIfEmpty(JsonResult.getInstance());
        }else {
            body = Mono.just((JsonResult<Object>)returnValue);
        }

        return writeBody(body, bodyTypeParameter, serverWebExchange);
    }
}
